package com.zhkc.wisdom.common.mybatis.encrypt.interceptor;

import com.zhkc.wisdom.common.mybatis.encrypt.annotation.SensitiveClass;
import com.zhkc.wisdom.common.mybatis.encrypt.utils.EncryptUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Objects;
import java.util.Properties;

/**
 * .
 *
 * @author kehong liu
 */
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
@Slf4j
public class ParameterInterceptor implements Interceptor {

    @Value("${zhkc.table.encryptPass:niqowehoqwe}")
    private String encryptPass;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // @Signature 指定了 type= parameterHandler 后，这里的 invocation.getTarget()
        // 便是parameterHandler
        // 若指定ResultSetHandler ，这里则能强转为ResultSetHandler
        String methodName = invocation.getMethod().getName();
        if (!"update".equalsIgnoreCase(methodName) && !"insert".equalsIgnoreCase(methodName)) {
            return invocation.proceed();
        }
        Object parameterObject = null;
        try {
            parameterObject = getObject(invocation);
        } catch (Exception ex) {
            log.error("param is error");
        }

        if (parameterObject != null) {
            Class<?> parameterObjectClass = parameterObject.getClass();
            // 校验该实例的类是否被@SensitiveClass所注解
            SensitiveClass sensitiveData = AnnotationUtils.findAnnotation(parameterObjectClass, SensitiveClass.class);
            if (Objects.nonNull(sensitiveData)) {
                // 取出当前当前类所有字段，传入加密方法
                Field[] declaredFields = parameterObjectClass.getDeclaredFields();
                EncryptUtil.encrypt(declaredFields, parameterObject, this.encryptPass);
            }
        }
        return invocation.proceed();
    }

    private Object getObject(Invocation invocation) {
        // 获取该sql语句放入的参数
        Object parameterObject = invocation.getArgs()[1];
        if (parameterObject instanceof ParameterMap) {
            MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) invocation.getArgs()[1];
            parameterObject = paramMap.get("param1");
        }

        if (parameterObject instanceof MapperMethod.ParamMap) {
            MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) invocation.getArgs()[1];
            try {
                parameterObject = paramMap.get("et");
            } catch (Exception ex) {
                parameterObject = paramMap.get("param1");
            }
        }
        return parameterObject;
    }

    /**
     * 切记配置，否则当前拦截器不会加入拦截器链.
     */
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // .
    }

}
